package com.ecommerce.config;

import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;

import javax.annotation.PreDestroy;
import java.io.IOException;
import java.time.Duration;

/**
 * Elasticsearch 配置类
 * 负责配置和初始化 Elasticsearch 客户端连接
 */
@Configuration
@EnableElasticsearchRepositories(basePackages = "com.ecommerce.dao.es")  // 明确指定 Elasticsearch Repository 扫描路径
@Slf4j
public class ElasticsearchConfig {
    /**
     * Elasticsearch 高级客户端实例
     * 用于在整个应用生命周期内保持连接
     */
    private RestHighLevelClient client; // 存储 client 以便后续关闭

    /**
     * Elasticsearch 服务器连接地址
     * 配置项来自 application.properties/yml 的 spring.elasticsearch.uris
     */
    @Value("${spring.elasticsearch.uris}")
    private String elasticsearchUrl;

    /**
     * 连接超时时间（毫秒）
     * 默认值 3000 毫秒
     */
    @Value("${spring.elasticsearch.connection-timeout:3000}")
    private int connectionTimeout;

    /**
     * 套接字超时时间（毫秒）
     * 默认值 5000 毫秒
     */
    @Value("${spring.elasticsearch.socket-timeout:5000}")
    private int socketTimeout;

    /**
     * 创建并配置 Elasticsearch 高级客户端
     * Spring Data Elasticsearch 4.x+ 开始使用新的 Java API 客户端 (ElasticsearchClient)，但 ElasticsearchRestTemplate 仍基于旧的 RestHighLevelClient。新的api需要Java 17+，Spring Boot 3.x，Elasticsearch 8.x+
     *
     * @return 配置好的 RestHighLevelClient 实例
     * @throws BeanCreationException 当客户端创建失败时抛出
     */
    @Bean
    @SuppressWarnings("resource") // 明确告诉 IDEA：这个资源会被 Spring 管理，无需警告,带@PreDestroy 注解的close()方法能正确关闭 RestHighLevelClient
    public RestHighLevelClient elasticsearchClient() {
        try {
            ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                    .connectedTo(elasticsearchUrl.split(","))
                    .withConnectTimeout(Duration.ofMillis(connectionTimeout))
                    .withSocketTimeout(Duration.ofMillis(socketTimeout))
                    .build();

            this.client = RestClients.create(clientConfiguration).rest();
            return client;
        } catch (Exception e) {
            throw new BeanCreationException("Failed to create Elasticsearch client", e);
        }
    }

    /**
     * 应用关闭时清理 Elasticsearch 客户端连接
     * 使用 @PreDestroy 确保在 Spring 容器销毁前执行
     */
    @PreDestroy
    public void close() {
        if (client != null) {
            try {
                client.close();
                log.info("Elasticsearch client closed successfully");
            } catch (IOException e) {
                log.error("Error closing Elasticsearch client", e);
            }
        }
    }

    /**
     * 创建 ElasticsearchRestTemplate Bean
     * 用于简化 Elasticsearch 操作
     *
     * @param client 注入的 RestHighLevelClient 实例
     * @return 配置好的 ElasticsearchRestTemplate
     */
    @Bean
    public ElasticsearchRestTemplate elasticsearchOperations(RestHighLevelClient client) {
        return new ElasticsearchRestTemplate(client);
    }
}